import socket
import struct
import select
import time
import tkinter as tk
from tkinter import scrolledtext, messagebox

# 定义函数来解析域名获取所有IP地址
def get_ips_from_domain(domain):
    try:
        # 获取域名的所有IP地址
        ip_list = set()
        for addr_info in socket.getaddrinfo(domain, 80, family=socket.AF_UNSPEC, proto=socket.IPPROTO_TCP):
            ip = addr_info[4][0]
            ip_list.add(ip)
        return list(ip_list)
    except socket.gaierror as e:
        return f"无法解析域名: {domain} - {e}"

# 定义函数来发送ICMP请求并测量延迟
def ping_ip(ip, timeout=5):
    try:
        # 创建一个原始套接字
        icmp_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)
        icmp_socket.settimeout(timeout)

        # 构造ICMP包
        icmp_id = 1
        icmp_seq = 1
        checksum = 0
        header = struct.pack("!BBHHH", 8, 0, checksum, icmp_id, icmp_seq)
        data = b'P' * 32
        packet = header + data

        # 计算校验和
        checksum = in_checksum(packet)
        header = struct.pack("!BBHHH", 8, 0, checksum, icmp_id, icmp_seq)
        packet = header + data

        # 发送ICMP请求
        start_time = time.time()
        icmp_socket.sendto(packet, (ip, 0))

        # 接收ICMP响应
        ready = select.select([icmp_socket], [], [], timeout)
        if ready[0]:
            recv_packet, addr = icmp_socket.recvfrom(1024)
            end_time = time.time()
            delay = (end_time - start_time) * 1000  # 转换为毫秒
            return f"平均延迟: {delay:.2f} ms"
        else:
            return "请求超时"
    except Exception as e:
        return f"未知错误: {e}"
    finally:
        icmp_socket.close()

# 计算校验和
def in_checksum(source_string):
    sum = 0
    count_to = (len(source_string) // 2) * 2
    for i in range(0, count_to, 2):
        this_val = source_string[i+1] * 256 + source_string[i]
        sum = sum + this_val
        sum = sum & 0xffffffff  # 必要时进行截断
    if count_to < len(source_string):
        sum = sum + source_string[len(source_string) - 1]
        sum = sum & 0xffffffff  # 必要时进行截断
    sum = (sum >> 16) + (sum & 0xffff)
    sum = sum + (sum >> 16)
    answer = ~sum
    answer = answer & 0xffff
    answer = answer >> 8 | (answer << 8 & 0xff00)
    return answer

# 处理输入的网址
def process_domain():
    domain = entry.get().strip()
    if not domain:
        messagebox.showwarning("警告", "请输入一个有效的网址")
        return
    
    ip_list = get_ips_from_domain(domain)
    if isinstance(ip_list, str):  # 如果get_ips_from_domain返回了一个字符串，说明有错误
        result_text.delete(1.0, tk.END)
        result_text.insert(tk.END, ip_list)
        return
    
    results = []
    for ip in ip_list:
        result = ping_ip(ip)
        results.append(f"{ip}: {result}")
    
    result_text.delete(1.0, tk.END)
    result_text.insert(tk.END, "\n".join(results))

# 创建主窗口
root = tk.Tk()
root.title("测试网站IP延迟")

# 输入框
entry = tk.Entry(root, width=40)
entry.pack(pady=10)

# 按钮
button = tk.Button(root, text="测试延迟", command=process_domain)
button.pack(pady=5)

# 结果文本框
result_text = scrolledtext.ScrolledText(root, width=60, height=15)
result_text.pack(pady=10)

# 运行主循环
root.mainloop()